package co.gov.medellin.ssti.sub.model.dao.impl;

import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcDaoSupport;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.support.GeneratedKeyHolder;

import co.gov.medellin.ssti.sub.model.dao.SubprogramaSedeDAO;
import co.gov.medellin.ssti.sub.model.vo.SubprogramaSedeVO;

public class SubprogramaSedeDAOImpl2 extends NamedParameterJdbcDaoSupport
		implements SubprogramaSedeDAO {

	public Collection<SubprogramaSedeVO> findSubprogramaSedeByCriteria(
			SubprogramaSedeVO criteria) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		StringBuffer query = new StringBuffer(
				"SELECT SUBSEDE.CODIGO CODE, TO_CHAR(SUBSEDE.DESDE,'DD/MM/YYYY') DESDE, "
						+ " TO_CHAR(SUBSEDE.HASTA,'DD/MM/YYYY') HASTA, "
						+ " SUBSEDE.NUMERO_BENEFICIO, SUBSEDE.NUMERO_BEN_DISPONIBLE, "
						+ " SEDE.CODIGO CODESEDE, SEDE.NOMBRE NOMBRESEDE, "
						+ " SUBPRO.CODIGO CODESUBPROGRAMA, SUBPRO.NOMBRE NOMBRESUBPROGRAMA, "
						+ " PRO.CODIGO CODEPROGRAMA, PRO.NOMBRE NOMBREPROGRAMA "
						+ " FROM TCS_BEN_SUBPROGRAMA_SEDE SUBSEDE, "
						+ " TCS_BEN_SEDE SEDE, "
						+ " TCS_BEN_SUBPROGRAMA SUBPRO, "
						+ " TCS_BEN_PROGRAMA PRO "
						+ " WHERE SEDE.CODIGO = SUBSEDE.SEDE_CODIGO "
						+ " AND SUBPRO.CODIGO = SUBSEDE.SBPR_CODIGO "
						+ " AND SUBPRO.PRG_CODIGO =  PRO.CODIGO ");

		if ((Object) criteria.getCodeSede() != null) {
			query.append(" AND SEDE.CODIGO = :SEDE.CODIGO ");
			namedParameters.put("SEDE.CODIGO", criteria.getCodeSede());
		}
		if ((Object) criteria.getCodeSubprograma() != null) {
			query.append(" AND SUBPRO.CODIGO = :SUBPRO.CODIGO ");
			namedParameters.put("SUBPRO.CODIGO", criteria.getCodeSubprograma());
		}
		if ((Object) criteria.getCodePrograma() != null) {
			query.append(" AND PRO.CODIGO = :PRO.CODIGO ");
			namedParameters.put("PRO.CODIGO", criteria.getCodePrograma());
		}
		query.append(" ORDER BY PRO.NOMBRE,SUBPRO.NOMBRE,DESDE DESC, SEDE.NOMBRE ");

		List<SubprogramaSedeVO> lsubsede = getNamedParameterJdbcTemplate()
				.query(query.toString(), namedParameters,
						new RowMapper<SubprogramaSedeVO>() {

							public SubprogramaSedeVO mapRow(ResultSet rs,
									int arg1) throws SQLException {
								SubprogramaSedeVO vo = new SubprogramaSedeVO();
								vo.setCode(new Long(rs.getLong("CODE")));
								vo.setCodeSede(new Long(rs.getLong("CODESEDE")));
								vo.setNombreSede(rs.getString("NOMBRESEDE"));
								vo.setCodePrograma(new Long(rs
										.getLong("CODEPROGRAMA")));
								vo.setNombrePrograma(rs
										.getString("NOMBREPROGRAMA"));
								vo.setCodeSubprograma(new Long(rs
										.getLong("CODESUBPROGRAMA")));
								vo.setNombreSubprograma(rs
										.getString("NOMBRESUBPROGRAMA"));
								vo.setDesde(rs.getString("DESDE"));
								vo.setHasta(rs.getString("HASTA"));
								vo.setCantidadTotal(rs
										.getString("NUMERO_BENEFICIO"));
								vo.setCantidadDisponible(rs
										.getString("NUMERO_BEN_DISPONIBLE"));
								return vo;
							}
						});
		return lsubsede;
	}

	public Collection<SubprogramaSedeVO> findSubprogramaSedeByCode(
			Long codeSubprogramaSede) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		String query = "SELECT SUBSEDE.CODIGO CODE, TO_CHAR(SUBSEDE.DESDE,'DD/MM/YYYY') DESDE, "
				+ " TO_CHAR(SUBSEDE.HASTA,'DD/MM/YYYY') HASTA, "
				+ " SUBSEDE.NUMERO_BENEFICIO, SUBSEDE.NUMERO_BEN_DISPONIBLE, "
				+ " SEDE.CODIGO CODESEDE, SEDE.NOMBRE NOMBRESEDE, "
				+ " SUBPRO.CODIGO CODESUBPROGRAMA, SUBPRO.NOMBRE NOMBRESUBPROGRAMA, "
				+ " PRO.CODIGO CODEPROGRAMA, PRO.NOMBRE NOMBREPROGRAMA "
				+ " FROM TCS_BEN_SUBPROGRAMA_SEDE SUBSEDE, "
				+ " TCS_BEN_SEDE SEDE, "
				+ " TCS_BEN_SUBPROGRAMA SUBPRO, "
				+ " TCS_BEN_PROGRAMA PRO "
				+ " WHERE SEDE.CODIGO = SUBSEDE.SEDE_CODIGO "
				+ " AND SUBPRO.CODIGO = SUBSEDE.SBPR_CODIGO "
				+ " AND SUBPRO.PRG_CODIGO =  PRO.CODIGO "
				+ " AND SUBSEDE.CODIGO = :CODIGO ";

		query += " ORDER BY PRO.NOMBRE,SUBPRO.NOMBRE,DESDE DESC, SEDE.NOMBRE ";

		namedParameters.put("CODIGO", codeSubprogramaSede);

		List<SubprogramaSedeVO> lsubsede = getNamedParameterJdbcTemplate()
				.query(query, namedParameters,
						new RowMapper<SubprogramaSedeVO>() {

							public SubprogramaSedeVO mapRow(ResultSet rs,
									int rowNum) throws SQLException {
								SubprogramaSedeVO vo = new SubprogramaSedeVO();
								vo.setCode(new Long(rs.getLong("CODE")));
								vo.setCodeSede(new Long(rs.getLong("CODESEDE")));
								vo.setNombreSede(rs.getString("NOMBRESEDE"));
								vo.setCodePrograma(new Long(rs
										.getLong("CODEPROGRAMA")));
								vo.setNombrePrograma(rs
										.getString("NOMBREPROGRAMA"));
								vo.setCodeSubprograma(new Long(rs
										.getLong("CODESUBPROGRAMA")));
								vo.setNombreSubprograma(rs
										.getString("NOMBRESUBPROGRAMA"));
								vo.setDesde(rs.getString("DESDE"));
								vo.setHasta(rs.getString("HASTA"));
								vo.setCantidadTotal(rs
										.getString("NUMERO_BENEFICIO"));
								vo.setCantidadDisponible(rs
										.getString("NUMERO_BEN_DISPONIBLE"));
								return vo;
							}
						});
		return lsubsede;
	}

	public void insertUsuarioSede(Long codeSubprogramaSede, Long codeUser,
			String[] param) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		String query = "SELECT codigo FROM TCS_BEN_USUARIO_SEDE "
				+ " WHERE usu_codigo = :usu_codigo AND spse_codigo = :spse_codigo ";

		namedParameters.put("usu_codigo", codeUser);
		namedParameters.put("spse_codigo", codeSubprogramaSede);

		try {
			String codigo = getNamedParameterJdbcTemplate().queryForObject(
					query, namedParameters, String.class);
			if (codigo != null) {
				return;
			}
		} catch (IncorrectResultSizeDataAccessException e) {
			// TODO: handle exception
		}
		namedParameters.clear();
		query = "INSERT INTO TCS_BEN_USUARIO_SEDE "
				+ " (CODIGO, USU_CODIGO, SPSE_CODIGO, "
				+ " usuario_crea, fecha_crea, terminal_crea, usuario_modifica, fecha_modifica, terminal_modifica) "
				+ " VALUES (SCS_BEN_USE.nextval, :USU_CODIGO, :SPSE_CODIGO, :usuario_crea, TO_DATE(:fecha_crea,'dd/mm/yyyy'), :terminal_crea, :usuario_modifica, TO_DATE(:fecha_modifica,'dd/mm/yyyy'), :terminal_modifica)";

		namedParameters.put("USU_CODIGO", codeUser);
		namedParameters.put("SPSE_CODIGO", codeSubprogramaSede);
		namedParameters.put("usuario_crea", param[0]); // user.getName()
		namedParameters.put("fecha_crea", param[1]); // dateFormat.format(c.getTime())
		namedParameters.put("terminal_crea", param[2]); // strTerminal
		namedParameters.put("usuario_modifica", param[3]); // user.getName()
		namedParameters.put("fecha_modifica", param[4]); // dateFormat.format(c.getTime())
		namedParameters.put("terminal_modifica", param[5]); // strTerminal
		getNamedParameterJdbcTemplate().update(query, namedParameters);

	}

	public String[] insertSubprogramaSede(Long codeSede, Long codeSubprograma,
			String desde, String hasta, String cantidad, String[] param) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		String retorno[] = new String[2];
		retorno[0] = "false";

		int validate1 = validateExist(codeSede, codeSubprograma, desde, hasta);

		if (validate1 == 0) {
			String usuarioCrea = param[0];
			String fechaCrea = param[1];
			String terminalCrea = param[2];
			String usuarioModifica = param[3];
			String fechaModifica = param[4];
			String terminalModifica = param[5];
			int iCantidad = new Integer(cantidad).intValue();
			if (validateExist(codeSede, codeSubprograma)) {
				String validate[] = validateDates(codeSede, codeSubprograma,
						desde);
				if (validate[0].equals("true")) {
					// {user.getName(),
					// dateFormat.format(c.getTime()),strTerminal,user.getName(),
					// dateFormat.format(c.getTime()),strTerminal};
					String query = "INSERT INTO TCS_BEN_SUBPROGRAMA_SEDE "
							+ " (CODIGO, SEDE_CODIGO, SBPR_CODIGO, "
							+ " DESDE, HASTA, NUMERO_BENEFICIO, "
							+ " NUMERO_BEN_DISPONIBLE, "
							+ " usuario_crea, fecha_crea, terminal_crea, usuario_modifica, fecha_modifica, terminal_modifica) "
							+ " VALUES (SCS_BEN_SPSE.nextval, :SEDE_CODIGO, :SBPR_CODIGO,"
							+ " TO_DATE(:DESDE,'dd/mm/yyyy'), TO_DATE(:HASTA,'dd/mm/yyyy'), :NUMERO_BENEFICIO, :NUMERO_BEN_DISPONIBLE, :usuario_crea, TO_DATE(:fecha_crea,'dd/mm/yyyy'), :terminal_crea, :usuario_modifica, TO_DATE(:fecha_modifica,'dd/mm/yyyy'), :terminal_modifica)";

					namedParameters.put("SEDE_CODIGO", codeSede);
					namedParameters.put("SBPR_CODIGO", codeSubprograma);
					namedParameters.put("DESDE", desde);
					namedParameters.put("HASTA", hasta);
					namedParameters.put("NUMERO_BENEFICIO", iCantidad);
					namedParameters.put("NUMERO_BEN_DISPONIBLE", iCantidad);
					namedParameters.put("usuario_crea", usuarioCrea);
					namedParameters.put("fecha_crea", fechaCrea);
					namedParameters.put("terminal_crea", terminalCrea);
					namedParameters.put("usuario_modifica", usuarioModifica);
					namedParameters.put("fecha_modifica", fechaModifica);
					namedParameters.put("terminal_modifica", terminalModifica);

					GeneratedKeyHolder generatedKeyHolder = new GeneratedKeyHolder();
					SqlParameterSource parameterSource = new MapSqlParameterSource(
							namedParameters);
					try {
						getNamedParameterJdbcTemplate().update(query,
								parameterSource, generatedKeyHolder,
								new String[] { "CODIGO" });

						Long secuenciaInsertado = null;

						secuenciaInsertado = generatedKeyHolder.getKey()
								.longValue();
						if (secuenciaInsertado != null) {
							retorno[0] = "true";
							retorno[1] = Long.toString(secuenciaInsertado);
						} else {
							retorno[0] = "false";
						}
					} catch (Exception e) {
						retorno[0] = "false";
					}
				} else {
					if ((Object) validate[1] != null) {
						// indica que solo se debe insertar
						retorno[0] = "ususede";
						retorno[1] = validate[1];
					} else {
						retorno[1] = "Ese beneficio ya esta cubierto en ese periodo de tiempo, seleccione otro rango!";
					}
				}
			} else {// esto es duplicado.. luego lo reviso mejor.
				String query = "INSERT INTO TCS_BEN_SUBPROGRAMA_SEDE "
						+ " (CODIGO, SEDE_CODIGO, SBPR_CODIGO, "
						+ " DESDE, HASTA, NUMERO_BENEFICIO, "
						+ " NUMERO_BEN_DISPONIBLE, "
						+ " usuario_crea, fecha_crea, terminal_crea, usuario_modifica, fecha_modifica, terminal_modifica) "
						+ " VALUES (SCS_BEN_SPSE.nextval, :SEDE_CODIGO, :SBPR_CODIGO,"
						+ " TO_DATE(:DESDE,'dd/mm/yyyy'), TO_DATE(:HASTA,'dd/mm/yyyy'), :NUMERO_BENEFICIO, :NUMERO_BEN_DISPONIBLE, :usuario_crea, TO_DATE(:fecha_crea,'dd/mm/yyyy'), :terminal_crea, :usuario_modifica, TO_DATE(:fecha_modifica,'dd/mm/yyyy'), :terminal_modifica)";

				namedParameters.clear();
				namedParameters.put("SEDE_CODIGO", codeSede);
				namedParameters.put("SBPR_CODIGO", codeSubprograma);
				namedParameters.put("DESDE", desde);
				namedParameters.put("HASTA", hasta);
				namedParameters.put("NUMERO_BENEFICIO", iCantidad);
				namedParameters.put("NUMERO_BEN_DISPONIBLE", iCantidad);
				namedParameters.put("usuario_crea", usuarioCrea);
				namedParameters.put("fecha_crea", fechaCrea);
				namedParameters.put("terminal_crea", terminalCrea);
				namedParameters.put("usuario_modifica", usuarioModifica);
				namedParameters.put("fecha_modifica", fechaModifica);
				namedParameters.put("terminal_modifica", terminalModifica);

				GeneratedKeyHolder generatedKeyHolder = new GeneratedKeyHolder();
				SqlParameterSource parameterSource = new MapSqlParameterSource(
						namedParameters);
				try {
					getNamedParameterJdbcTemplate().update(query,
							parameterSource, generatedKeyHolder,
							new String[] { "CODIGO" });

					Long secuenciaInsertado = null;

					secuenciaInsertado = generatedKeyHolder.getKey()
							.longValue();
					if (secuenciaInsertado != null) {
						retorno[0] = "true";
						retorno[1] = Long.toString(secuenciaInsertado);
					} else {
						retorno[0] = "false";
					}
				} catch (Exception e) {
					retorno[0] = "false";
				}
			}
		} else {
			// "La sede seleccionada ya tiene asignado ese beneficio en el mismo periodo de tiempo";
			retorno[0] = "ususede";
			retorno[1] = validate1 + "";
		}
		return retorno;
	}

	public boolean actualizarSubproSede(Long codeSubprogramaSede,
			String[] parArr) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		String query = "UPDATE TCS_BEN_SUBPROGRAMA_SEDE SET "
				+ " SEDE_CODIGO = :SEDE_CODIGO, DESDE = TO_DATE(:DESDE,'dd/mm/yyyy'), "
				+ " HASTA = TO_DATE(:HASTA,'dd/mm/yyyy'), "
				+ " NUMERO_BENEFICIO = NUMERO_BENEFICIO + :cantidad, "
				+ " NUMERO_BEN_DISPONIBLE = NUMERO_BEN_DISPONIBLE + :cantidad, "
				+ " usuario_modifica = :usuario_modifica, "
				+ " fecha_modifica = TO_DATE(:fecha_modifica,'dd/mm/yyyy'), "
				+ " terminal_modifica = :terminal_modifica WHERE CODIGO = :CODIGO";// +
																					// code;
		// {strCodeSede,desde,hasta,cantidad,cantidad,user.getName(),dateFormat.format(c.getTime()),strTerminal};

		Long codeSede = new Long(parArr[0]); // strCodeSede
		String desde = parArr[1];// desde
		String hasta = parArr[2];
		Integer cantidad = new Integer(parArr[3]);
		String usuario = parArr[4];
		String fechaModifica = parArr[5];
		String terminal = parArr[6];

		namedParameters.put("SEDE_CODIGO", codeSede);
		namedParameters.put("DESDE", desde);
		namedParameters.put("HASTA", hasta);
		namedParameters.put("cantidad", cantidad);
		// namedParameters.put("cantidad", cantidad);
		namedParameters.put("usuario_modifica", usuario);
		namedParameters.put("fecha_modifica", fechaModifica);
		namedParameters.put("terminal_modifica", terminal);
		namedParameters.put("CODIGO", codeSubprogramaSede);

		return (getNamedParameterJdbcTemplate().update(query, namedParameters) > 0) ? true
				: false;
	}

	private int validateExist(Long codeSede, Long codeSubprograma,
			String desde, String hasta) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		String query = "SELECT codigo FROM TCS_BEN_SUBPROGRAMA_SEDE "
				+ " WHERE sede_codigo = :sede_codigo AND sbpr_codigo = :sbpr_codigo "
				+ " AND desde = TO_DATE(:DESDE,'dd/mm/yyyy')"
				+ " AND hasta = TO_DATE(:HASTA,'dd/mm/yyyy')";

		namedParameters.put("sede_codigo", codeSede);
		namedParameters.put("sbpr_codigo", codeSubprograma);
		namedParameters.put("DESDE", desde);
		namedParameters.put("HASTA", hasta);

		try {
			int codigo = getNamedParameterJdbcTemplate().queryForObject(query,
					namedParameters, Integer.class);
			return codigo;
		} catch (IncorrectResultSizeDataAccessException e) {
			// TODO: handle exception
			return 0;
		}
	}

	private boolean validateExist(Long codeSede, Long codeSubprograma) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		String query = "SELECT codigo FROM TCS_BEN_SUBPROGRAMA_SEDE "
				+ " WHERE sede_codigo = :sede_codigo AND sbpr_codigo = :sbpr_codigo";

		namedParameters.put("sede_codigo", codeSede);
		namedParameters.put("sbpr_codigo", codeSubprograma);
		try {
			String codigo = getNamedParameterJdbcTemplate().queryForObject(
					query, namedParameters, String.class);
			if (codigo != null) {
				return true;
			}
			return false;
		} catch (IncorrectResultSizeDataAccessException e) {
			// TODO: handle exception
			return false;
		}
	}

	// TODO: tstst
	private String[] validateDates(Long codeSede, Long codeSubprograma,
			String desde) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		String query = "SELECT case WHEN hasta < TO_DATE(:DESDE,'dd/mm/yyyy') THEN 'true' "
				+ " ELSE 'false' "
				+ " END validacion, codigo "
				+ " FROM tcs_ben_subprograma_sede "
				+ " WHERE codigo =  (SELECT MAX(codigo) FROM tcs_ben_subprograma_sede "
				+ " WHERE sbpr_codigo = :sbpr_codigo AND sede_codigo = :sede_codigo )";
		String retorno[] = new String[2];

		namedParameters.put("DESDE", desde);
		namedParameters.put("sbpr_codigo", codeSubprograma);
		namedParameters.put("sede_codigo", codeSede);

		List<Map<String, Object>> rows = getNamedParameterJdbcTemplate()
				.queryForList(query, namedParameters);
		if (rows.isEmpty()) {
			retorno[0] = "false";
		} else {
			for (Map<String, Object> row : rows) {
				String test = (String) row.get("validacion");
				retorno[0] = test;
				retorno[1] = ((BigDecimal) row.get("codigo")).toString();
			}
		}
		return retorno;
	}

}
